
package com.xifan.myaccount;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.NumberPicker;
import android.widget.NumberPicker.OnValueChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.hb.views.PinnedSectionListView;
import com.xifan.myaccount.adapter.DetailListAdapter;
import com.xifan.myaccount.adapter.DrawerAdapter;
import com.xifan.myaccount.database.DatabaseImpl;
import com.xifan.myaccount.entity.Account;
import com.xifan.myaccount.entity.RecordDetail;
import com.xifan.myaccount.util.UiHelper;
import com.xifan.myaccount.util.Util;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {
    private List<RecordDetail> mDetailList;
    private List<RecordDetail> mPickDelList;
    private DetailListAdapter mAdapter;
    private Context mContext;

    private LinearLayout mFloatingBar;
    private PinnedSectionListView mListView;
    private TextView msgText;
    private TextView expendText;
    private TextView revenueText;
    private TextView totalText;
    private DrawerLayout mDrawer;
    private ActionBarDrawerToggle mDrawerToggle;
    private ListView mDrawerList;
    private Button mCalendarBtn;

    private LoadTask mTask;

    private String[] mMonthArray;
    private float firstY;

    private int mCurrentAccount = Account.DEFAULT_ACCOUNT_ID;
    private float mExpend = 0f;
    private float mRevenue = 0f;
    private float mTotal = 0f;
    private boolean enableScroll = true;
    private boolean canListScroll = false;
    private int mSelectedMonth = -1;

    private static final int REQUEST_SHOW_FLAG = 3;
    public static final int LOCATION_REFRESH_INTERVAL = 30;

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        mDetailList = new ArrayList<RecordDetail>();
        mPickDelList = new ArrayList<RecordDetail>();
        mContext = this;

        mTask = new LoadTask();
        mTask.execute();

        initView();
    }

    private void initView() {
        mFloatingBar = (LinearLayout) findViewById(R.id.floating_bar);
        mCalendarBtn = (Button) findViewById(R.id.calendar_chooser_btn);
        mListView = (PinnedSectionListView) findViewById(R.id.account_detail_list);
        msgText = (TextView) findViewById(R.id.message);
        expendText = (TextView) findViewById(R.id.account_expend_of_month_value);
        revenueText = (TextView) findViewById(R.id.account_revenue_of_month_value);
        totalText = (TextView) findViewById(R.id.account_total_of_month_value);
        mDrawer = (DrawerLayout) findViewById(R.id.drawer);
        mDrawerList = (ListView) findViewById(R.id.drawer_list);

        mCalendarBtn.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                AlertDialog monthDialog = UiHelper.createMonthPickerDialog(mContext,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                if (which == Dialog.BUTTON_POSITIVE) {
                                    mCalendarBtn.setText(mMonthArray[mSelectedMonth]);
                                    mTask = new LoadTask();
                                    mTask.execute();
                                }
                            }
                        }, new OnValueChangeListener() {
                            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                                mSelectedMonth = newVal - 1;
                            }
                        }, mSelectedMonth, getString(R.string.month_dialog_title));
                monthDialog.show();
            }
        });

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawer,
                R.drawable.ic_drawer, R.string.app_name, R.string.app_name) {
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }
        };
        mDrawer.setDrawerListener(mDrawerToggle);

        initListView();
    }

    private void initListView() {
        mListView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                RecordDetail detail = mDetailList.get(position);
                if (detail.getPinnedTag() != 1) {
                    Intent intent = new Intent(mContext, ShowRecord.class);
                    intent.putExtra("detail", detail);
                    startActivityForResult(intent, REQUEST_SHOW_FLAG);
                }
            }
        });
        mListView.setOnTouchListener(new OnTouchListener() {

            private final AnimationSet hideAnim = (AnimationSet) AnimationUtils.loadAnimation(
                    mContext, R.anim.hide_t2b);

            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        firstY = event.getAxisValue(MotionEvent.AXIS_Y);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mFloatingBar.getVisibility() == View.GONE) {
                            if (canListScroll && event.getAxisValue(MotionEvent.AXIS_Y) > firstY) {
                                mFloatingBar.setVisibility(View.VISIBLE);
                            }
                        } else if (mFloatingBar.getVisibility() == View.VISIBLE && canListScroll
                                && firstY > event.getAxisValue(MotionEvent.AXIS_Y)) {
                            mFloatingBar.startAnimation(hideAnim);
                            mFloatingBar.setVisibility(View.GONE);
                        } else if (mFloatingBar.getVisibility() == View.VISIBLE && !enableScroll) {
                            // This controlled by multi choice mode
                            // if false,then it's in the mode
                            // then hide it anyway.
                            mFloatingBar.setVisibility(View.GONE);
                        }
                        break;
                }

                return false;
            }
        });
        mListView.setOnScrollListener(new OnScrollListener() {
            private int visibleItem;

            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (enableScroll)
                    canListScroll = visibleItem - view.getLastVisiblePosition() > 1;
            }

            // this method will be called when init view.
            // check if user touched screen then let it scroll.
            // and this will be called only when list can be scrolled.
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                    int totalItemCount) {
                if (enableScroll)
                    canListScroll = totalItemCount > visibleItemCount;
            }
        });
        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        mListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                for (int i = 0, s = mPickDelList.size(); i < s; i++) {
                    mPickDelList.get(i).setState(0);
                }
                return true;
            }

            public void onDestroyActionMode(ActionMode mode) {
                mAdapter.setCheckMode(false);
                mAdapter.notifyDataSetChanged();
                enableScroll = true;
                mFloatingBar.setVisibility(View.VISIBLE);
            }

            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.main_context_menu, menu);

                mAdapter.setCheckMode(true);
                // prevent scroll after data changed
                enableScroll = false;
                canListScroll = false;
                mFloatingBar.setVisibility(View.GONE);
                return true;
            }

            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.delete:
                        deleteItems();
                        mode.finish();
                        return true;
                    default:
                        return false;
                }
            }

            public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
                    boolean checked) {
                RecordDetail item = mDetailList.get(position);
                if (item.getPinnedTag() == 1) {
                    return;
                }
                if (checked) {
                    mPickDelList.add(item);
                } else {
                    mPickDelList.remove(item);
                }
                mAdapter.setCheckItem(position, checked);
                mAdapter.notifyDataSetChanged();
            }
        });

        mDrawerList.setAdapter(new DrawerAdapter(mContext));
        mDrawerList.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mDrawer.closeDrawers();
                switch (position) {
                    case 0:
                        break;
                    case 1:
                        Intent i = new Intent(mContext, Statistics.class);
                        startActivity(i);
                        break;
                    case 2:
                        Intent intent = new Intent(mContext, SettingsActivity.class);
                        intent.putExtra("entry", UiHelper.START_ACCOUNT_MANAGER);
                        startActivityForResult(intent, 0);
                        break;
                    case 3:
                        Intent intent1 = new Intent(mContext, SettingsActivity.class);
                        intent1.putExtra("entry", UiHelper.START_SETTINGS);
                        startActivity(intent1);
                        break;
                }
            }
        });
    }

    protected void deleteItems() {
        if (mPickDelList.size() > 0) {
            DatabaseImpl db = new DatabaseImpl(mContext, true);
            for (RecordDetail detail : mPickDelList) {
                db.doDelete("detail", "id=?", new String[] {
                        String.valueOf(detail.getId())
                });
                db.syncAccount(detail.getRawMoney(), detail.getRecordType(),
                        detail.getAccountId(),
                        -detail.getOperateType());
                mDetailList.remove(detail);
            }
            db.close();
            mPickDelList.clear();
            Toast.makeText(mContext, getResources().getString(R.string.msg_deleted),
                    Toast.LENGTH_SHORT).show();

            mTask = new LoadTask();
            mTask.execute();
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_add:
                Intent intent = new Intent(mContext, AddRecord.class);
                startActivityForResult(intent, UiHelper.START_ADD_RECORD);
                break;
            case android.R.id.home:
                if (mDrawer.isDrawerOpen(Gravity.LEFT))
                    mDrawer.closeDrawer(Gravity.LEFT);
                else
                    mDrawer.openDrawer(Gravity.LEFT);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            mTask = new LoadTask();
            mTask.execute();
        }
    }

    private class LoadTask extends AsyncTask<Void, Void, List<RecordDetail>> {
        @SuppressWarnings("unchecked")
        protected List<RecordDetail> doInBackground(Void... params) {
            DatabaseImpl db = new DatabaseImpl(mContext);
            mCurrentAccount = Util.getCurrentAccountId(mContext);
            if (mSelectedMonth == -1)
                mSelectedMonth = Util.getMonth();
            String defaultDate = Util.getDatetimeByMonth(mSelectedMonth);

            List<RecordDetail> tmpList = db
                    .doQuery(DatabaseImpl.DB_TABLE_DETAIL,
                            "where accountId="
                                    + mCurrentAccount
                                    + " and strftime('%m',recordDate)=strftime('%m','"
                                    + defaultDate + "')", true);

            if (tmpList.size() < 0) {
                Log.w("xifan", "data is null");
                // check if account exist
                List<Account> tmpAccountList = db.doQuery("account", "", false);
                if (tmpAccountList.size() < 0) {
                    // doesn't exists
                    Log.w("xifan", "db is null,initializing");
                    db.initDataBase();
                }
            }

            // Adding headers to list
            List<RecordDetail> pinnedList = new ArrayList<RecordDetail>();
            int pinCount = 0;
            int operate = -1;
            for (int i = 0, s = tmpList.size(); i < s; i++) {
                RecordDetail tmpDetail = tmpList.get(i);
                if (pinCount < 1) {
                    RecordDetail record = new RecordDetail();
                    record.setDate(tmpDetail.getDate());
                    record.setPinnedTag(1);
                    pinnedList.add(record);
                    pinCount++;
                }
                pinnedList.add(tmpDetail);
                if (i + 1 < s
                        && !tmpDetail.getOnlyDate().equals(tmpList.get(i + 1).getOnlyDate())) {
                    RecordDetail record = new RecordDetail();
                    record.setDate(tmpList.get(i + 1).getDate());
                    record.setPinnedTag(1);
                    pinnedList.add(record);
                    pinCount++;
                }

                operate = tmpDetail.getOperateType();
                if (operate == 1) {
                    mExpend += tmpDetail.getRawMoney();
                } else if (operate == 2) {
                    mRevenue += tmpDetail.getRawMoney();
                }
            }
            mTotal = mRevenue - mExpend;
            tmpList = pinnedList;

            mMonthArray = getResources().getStringArray(R.array.months);

            return tmpList;
        }

        @Override
        protected void onPostExecute(List<RecordDetail> result) {
            super.onPostExecute(result);

            mDetailList = result;
            mAdapter = new DetailListAdapter(mContext, mDetailList);
            mAdapter.notifyDataSetChanged();
            mCalendarBtn.setText(mMonthArray[mSelectedMonth]);
            msgText.setText(R.string.msg_no_details);
            msgText.setVisibility(mDetailList.size() > 0 ? View.GONE : View.VISIBLE);
            mListView.setAdapter(mAdapter);
            expendText.setText(String.valueOf(mExpend));
            revenueText.setText(String.valueOf(mRevenue));
            totalText.setText(String.valueOf(mTotal));

            clearCount();
        }

        private void clearCount() {
            mExpend = 0f;
            mRevenue = 0f;
            mTotal = 0f;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mTask.cancel(true);
    }

}
